package com.lebang.service.sys;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.lebang.common.AliPayConfig.PayConstants;
import com.lebang.common.util.DateUtil;
import com.lebang.domain.CencesIdentityCard;
import com.lebang.domain.MemberCashFastWithdrawal;
import com.lebang.domain.MemberCashWithdrawal;
import com.lebang.entity.RequestHeaders;
import com.lebang.entity.member.LbbMember;
import com.lebang.entity.member.LbbMemberTrade;
import com.lebang.example.MemberCashWithdrawalExample;
import com.lebang.mapper.LbbMemberMapper;
import com.lebang.mapper.LbbMemberTradeMapper;
import com.lebang.mapper.MemberCashFastWithdrawalMapper;
import com.lebang.mapper.MemberCashWithdrawalMapper;
import com.lebang.model.cences.IdentityCardCount;
import com.lebang.model.enums.CheckStatus;
import com.lebang.model.enums.Gender;
import com.lebang.model.enums.ResultVo;
import com.lebang.model.enums.buss.RewardType;
import com.lebang.model.enums.buss.TradeCategory;
import com.lebang.model.enums.buss.TradeStatus;
import com.lebang.service.BaseService;
import com.lebang.service.MemberNoticeService;
import com.lebang.service.WxPayService;
import com.lebangweb.common.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 新提现
 *
 * @Author hwq
 * @Date 2020-05-19
 */
@Service
@Slf4j
public class MemberCashWithdrawalService extends BaseService<MemberCashWithdrawal, Long, MemberCashWithdrawalExample> {
    @Autowired
    private MemberCashWithdrawalMapper memberCashWithdrawalMapper;
    @Autowired
    private MemberNoticeService memberNoticeService;
    @Value("${zfb.ALI_URL}")
    private String ALI_URL;
    @Value("${zfb.ALI_APP_ID}")
    private String ALI_APP_ID;
    @Value("${zfb.ALI_PRIVATE_KEY}")
    private String ALI_PRIVATE_KEY;
    @Value("${zfb.ALI_PUBLIC_KEY}")
    private String ALI_PUBLIC_KEY;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private LbbMemberTradeMapper lbbMemberTradeMapper;
    @Autowired
    private MemberCashFastWithdrawalMapper fastWithdrawalMapper;
    @Autowired
    private LbbMemberMapper lbbMemberMapper;

    /**
     * 申请提现
     *
     * @param member
     * @param type           1 支付宝 2微信
     * @param amount         金额 分
     * @param requestHeaders 请求头
     * @return
     */
    public boolean creatWishCash(LbbMember member, int type, int amount, RequestHeaders requestHeaders) {
        MemberCashWithdrawal trade = new MemberCashWithdrawal();
        String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        String tradeNo = "";
        trade.setImei(requestHeaders.getImei());
        trade.setIpAddr(requestHeaders.getIpAddr());
        trade.setMacAddr(requestHeaders.getMacAddr());
        trade.setAmount(amount);
        trade.setAppStore(requestHeaders.getAppStore());
        trade.setMemberId(member.getMemberId());
        trade.setTitle("提现-" + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE));
        trade.setVersion(requestHeaders.getVersion());
        trade.setCheckStatus(CheckStatus.BUSS_CHECK.getIndex());
        trade.setCreateTime(LocalDateTime.now());
        //校验微信是否绑定
        if (type == 2) {
            tradeNo = "WX" + dateStr + UUIDUtil.NS();
            trade.setIcard(member.getWxIcard());
            trade.setTradeAccount(member.getWxOpenid());
            trade.setRealName(member.getWeixinName());
            trade.setCodeAddr(memberCashWithdrawalMapper.selectAddrByCode(member.getWxIcard().substring(0, 6)));
            trade.setIcardCode(member.getWxIcard().substring(0, 6));
        } else {
            tradeNo = "ZFB" + dateStr + UUIDUtil.M();
            trade.setIcard(member.getZfbIcard());
            trade.setTradeAccount(member.getAlipay());
            trade.setRealName(member.getAlipayName());
            trade.setCodeAddr(memberCashWithdrawalMapper.selectAddrByCode(member.getZfbIcard().substring(0, 6)));
            trade.setIcardCode(member.getZfbIcard().substring(0, 6));
        }
        int i = Integer.parseInt(trade.getIcard().substring(6, 10));

        trade.setBirthday(String.valueOf(LocalDate.now().getYear() - i));
        if (NumberUtils.createInteger(trade.getIcard().substring(16, 17)) % 2 == 0) {
            member.setGender(Gender.Female.getTitle());
        } else {
            member.setGender(Gender.Male.getTitle());
        }
        trade.setPhone(member.getPhone());
        trade.setSex(member.getGender());
        trade.setMethod(type);
        trade.setTradeNo(tradeNo);
        this.insertModel(trade);
        return trade.getId() != null;
    }

    /**
     * 查看是否有待审核记录
     *
     * @param memberId
     * @return
     */
    public boolean allow(String memberId) {
        return memberCashWithdrawalMapper.allow(memberId) != null;
    }

    public List<Map<String, String>> page(LocalDateTime star, LocalDateTime end, Integer page, Integer limit, String phone,
                                          Integer checkStatus, Integer method, String icrad, String realName, String imei) {
        return memberCashWithdrawalMapper.page(star, end, page, limit, phone,
                checkStatus, method, icrad, realName, imei);
    }

    public long count(LocalDateTime star, LocalDateTime end, String phone, Integer checkStatus,
                      Integer method, String icrad, String realName, String imei) {
        return memberCashWithdrawalMapper.count(star, end, phone, checkStatus,
                method, icrad, realName, imei);
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo checkSuccess(MemberCashWithdrawal trade, Integer payType, String mark, String userid) {
        ResultVo resultVo;
        BigDecimal i = new BigDecimal(trade.getAmount());
        i = i.divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN);
        if (payType.equals(1)) {
            trade.setPayType(1);
            try {
                resultVo = this.staffPayByZfb(trade.getTradeNo(), trade.getTradeAccount(), trade.getRealName(), mark, i);
            } catch (AlipayApiException e) {
                e.printStackTrace();
                resultVo = new ResultVo(false, "支付宝请求失败");
            }
        } else if (payType.equals(2)) {
            trade.setPayType(2);
            resultVo = this.staffPayByWx(trade, mark);
        } else {
            trade.setPayType(3);
            resultVo = this.staffPayByartificial();
        }
        if (resultVo.isSuccess()) {
            trade.setCheckStatus(CheckStatus.SUCCESS.getIndex());
            trade.setPayStaff(userid);
            trade.setTradeTime(LocalDateTime.now());
            trade.setNote(mark);
            String desc = "您申请的{money}提现审核成功！";
            String money = i.toString();
            desc = desc.replace("{money}", money);
            memberNoticeService.addNoticeAndPush("提现通知", desc, trade.getMemberId(), new RequestHeaders(trade));
            memberCashWithdrawalMapper.updateByPrimaryKeySelective(trade);
            LbbMemberTrade trade1 = new LbbMemberTrade();
            trade1.setCreateTime(DateUtil.localDateTimToDate(trade.getCreateTime()));
            trade1.setModifyTime(DateUtil.localDateTimToDate(trade.getModifyTime()));
            trade1.setHasDeleted("False");
            //标记是新版提现防止重复计算
            trade1.setOrderId("xxx");
            trade1.setMemberId(trade.getMemberId());
            trade1.setAppId("xianyu");
            trade1.setAppStore(trade.getAppStore());
            trade1.setVersion(trade.getVersion());
            trade1.setTitle(trade.getTitle());
            trade1.setAmount(trade.getAmount());
            trade1.setExtra(0);
            trade1.setRemark(trade.getRemark());
            trade1.setCategory(TradeCategory.Outlay);
            trade1.setType(RewardType.Cash);
            trade1.setStatus(TradeStatus.Success);
            trade1.setOs("");
            trade1.setOsv("");
            trade1.setIpAddr(trade.getIpAddr());
            trade1.setMacAddr(trade.getMacAddr());
            trade1.setImei(trade.getImei());
            trade1.setTradeNo(trade.getTradeNo());
            trade1.setRemittance(2);
            trade1.setMethod(trade.getPayType());
            trade1.setChecker(trade.getChecker());
            trade1.setPayStaff(trade.getPayStaff());
            trade1.setNote(trade.getNote());
            trade1.setCheckStatus(trade.getCheckStatus());
            trade1.setPayType(trade.getPayType());
            trade1.setTradeTime(DateUtil.localDateTimToDate(trade.getTradeTime()));
            trade1.setContent(trade.getId().toString());
            lbbMemberTradeMapper.insertSelective(trade1);

        }
        return resultVo;
    }

    /**
     * 支付宝自动转账
     **/
    public ResultVo staffPayByZfb(String tradeNo, String account, String realName, String mark, BigDecimal amount) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(ALI_URL, ALI_APP_ID, ALI_PRIVATE_KEY, PayConstants.FORMAT, PayConstants.CHARSET, ALI_PUBLIC_KEY, PayConstants.SIGN_TYPE);
        AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
        request.setBizContent("{" +
                "    \"out_biz_no\":\"" + tradeNo + "\"," +
                "    \"payee_type\":\"ALIPAY_LOGONID\"," +
                "    \"payee_account\":\"" + account + "\"," +
                "    \"amount\":\"" + amount + "\"," +
                "\"payee_real_name\":\"" + realName + "\"," +
                "    \"payer_show_name\":\"咸鱼\"," +
                "    \"remark\":\"" + mark + "\"," +
                "  }");
        AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            return new ResultVo(true, "转账成功");
        } else {
            return new ResultVo(false, response.getSubMsg());
        }
    }

    /**
     * 人工转账
     **/
    public ResultVo staffPayByartificial() {
        return new ResultVo(true, "转账成功");
    }

    /**
     * 微信企业付款（审核版）
     *
     * @param trade
     * @param mark
     * @return
     */
    public ResultVo staffPayByWx(MemberCashWithdrawal trade, String mark) {
        Map<String, String> result = wxPayService.weChatTransfer(trade.getTradeNo(), trade.getAmount().toString(), mark, trade.getIpAddr(), trade.getTradeAccount(), trade.getRealName());
        if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
            return new ResultVo(true, "转账成功");
        } else {
            // 当返回错误码为“SYSTEMERROR”时，请不要更换商户订单号，一定要使用原商户订单号重试，否则可能造成重复支付等资金风险。
            return new ResultVo(false, "[2001]转账失败:" + result.get("return_msg") + result.get("err_code_des"));
        }
    }

    /**
     * 微信企业付款(极速版)
     *
     * @param trade
     * @param mark
     * @return
     */
    public ResultVo staffPayByWx(int amount, String tradeNo, String openId, String mark, String ipAddr, String realName) {
        Map<String, String> result = wxPayService.weChatTransfer(tradeNo, String.valueOf(amount), mark, ipAddr, openId, realName);
        if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
            return new ResultVo(true, "转账成功");
        } else {
            // 当返回错误码为“SYSTEMERROR”时，请不要更换商户订单号，一定要使用原商户订单号重试，否则可能造成重复支付等资金风险。
            return new ResultVo(false, "[2001]转账失败:" + result.get("return_msg") + result.get("err_code_des"));
        }
    }

    public List<LbbMemberTrade> selectOrder(RequestHeaders requestHeaders) {
        return memberCashWithdrawalMapper.selectByMemberId(requestHeaders.getUserid());
    }

    public ResultVo creatFastWishCash(LbbMember member, Integer type, int amount, RequestHeaders requestHeaders, String tradeNo) {
        ResultVo resultVo;
        String mark = "快速提现成功";
        BigDecimal i = new BigDecimal(amount);
        i = i.divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN);
        if (type.equals(1)) {
            try {
                resultVo = this.staffPayByZfb(tradeNo, member.getAlipay(), member.getAlipayName(), mark, i);
            } catch (AlipayApiException e) {
                e.printStackTrace();
                resultVo = new ResultVo(false, "支付宝请求失败");
            }
        } else if (type.equals(2)) {
            resultVo = this.staffPayByWx(amount, tradeNo, member.getWxOpenid(), mark, requestHeaders.getIpAddr(), member.getWeixinName());
        } else {
            resultVo = this.staffPayByartificial();
        }
        if (resultVo.isSuccess()) {
            String desc = "您申请的{money}提现审核成功！";
            String money = i.toString();
            desc = desc.replace("{money}", money);
            memberNoticeService.addNoticeAndPush("提现通知", desc, member.getMemberId(), requestHeaders);
            LbbMemberTrade trade1 = new LbbMemberTrade();
            trade1.setCreateTime(new Date());
            trade1.setModifyTime(new Date());
            trade1.setHasDeleted("False");
            //标记是新版提现防止重复计算
            trade1.setOrderId("xxx");
            trade1.setMemberId(member.getMemberId());
            trade1.setAppId("xianyu");
            trade1.setAppStore(requestHeaders.getAppStore());
            trade1.setVersion(requestHeaders.getVersion());
            trade1.setTitle("提现-" + LocalDate.now().format(DateTimeFormatter.ISO_DATE));
            trade1.setAmount(amount);
            trade1.setExtra(0);
            trade1.setRemark(desc);
            trade1.setCategory(TradeCategory.Outlay);
            trade1.setType(RewardType.Cash);
            trade1.setStatus(TradeStatus.Success);
            trade1.setOs(requestHeaders.getOs());
            trade1.setOsv(requestHeaders.getOsv());
            trade1.setIpAddr(requestHeaders.getIpAddr());
            trade1.setMacAddr(requestHeaders.getMacAddr());
            trade1.setImei(requestHeaders.getImei());
            trade1.setTradeNo(tradeNo);
            trade1.setRemittance(2);
            trade1.setMethod(type);
            trade1.setNote(desc);
            trade1.setCheckStatus(3);
            trade1.setPayType(type);
            trade1.setTradeTime(new Date());
            trade1.setContent("");
            lbbMemberTradeMapper.insertSelective(trade1);
            MemberCashFastWithdrawal trade = new MemberCashFastWithdrawal();
            trade.setImei(requestHeaders.getImei());
            trade.setIpAddr(requestHeaders.getIpAddr());
            trade.setMacAddr(requestHeaders.getMacAddr());
            trade.setAmount(amount);
            trade.setAppStore(requestHeaders.getAppStore());
            trade.setMemberId(member.getMemberId());
            trade.setTitle("提现-" + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE));
            trade.setVersion(requestHeaders.getVersion());
            trade.setCreateTime(LocalDateTime.now());
            trade.setPhone(member.getPhone());
            //校验微信是否绑定
            if (type == 2) {
                trade.setTradeAccount(member.getWxOpenid());
                trade.setRealName(member.getWeixinName());
            } else {
                trade.setTradeAccount(member.getAlipay());
                trade.setRealName(member.getAlipayName());
            }
            trade.setMethod(type);
            trade.setTradeNo(tradeNo);
            trade.setCheckStatus(3);
            trade.setPayType(type);
            fastWithdrawalMapper.insertSelective(trade);
        }
        return resultVo;
    }


    public List<MemberCashWithdrawal> selectList(String memberId) {
        MemberCashWithdrawalExample example = new MemberCashWithdrawalExample();
        example.setOffset(0L);
        example.setLimit(10);
        example.setOrderByClause("create_time desc");
        example.createCriteria().andMemberIdEqualTo(memberId);
        List<MemberCashWithdrawal> list = memberCashWithdrawalMapper.selectByExample(example);
        List<MemberCashWithdrawal> list2 = fastWithdrawalMapper.selectList(memberId);
        list.addAll(list2);
        list = list.stream().sorted(Comparator.comparing(MemberCashWithdrawal::getCreateTime).reversed()).collect(Collectors.toList());
        Optional<LbbMember> member = Optional.ofNullable(lbbMemberMapper.selectById(memberId));
        list.forEach(s->{
            if(s.getMethod()==2){
                s.setTradeAccount(member.map(LbbMember::getNickname).orElse(""));
            }
        });
        return list;
    }


    public Integer getTotal(LocalDate starTime, LocalDate endTime) {
        return memberCashWithdrawalMapper.getTotal(starTime,endTime);
    }

    public List<IdentityCardCount> selectDate(LocalDate starTime, LocalDate endTime) {
        return memberCashWithdrawalMapper.selectByDate(starTime,endTime);
    }

    public void getData(List<IdentityCardCount> list, CencesIdentityCard cencesIdentityCard) {

            list.forEach(item->{
                cencesIdentityCard.setTotal(cencesIdentityCard.getTotal()+item.getCount());
                if(item.getSex().equals("男")){
                    cencesIdentityCard.setMen(cencesIdentityCard.getMen()+item.getCount());
                }
                if(item.getSex().equals("女")){
                    cencesIdentityCard.setWomen(cencesIdentityCard.getWomen()+item.getCount());
                }
                if(item.getBirthday()<12){
                    cencesIdentityCard.setTwelf(cencesIdentityCard.getTwelf()+item.getCount());
                }
                if(item.getBirthday()>=12&&item.getBirthday()<=14){
                    cencesIdentityCard.setForteen(cencesIdentityCard.getForteen()+item.getCount());
                }
                if(item.getBirthday()>=15&&item.getBirthday()<=17){
                    cencesIdentityCard.setSeventeen(cencesIdentityCard.getSeventeen()+item.getCount());
                }
                if(item.getBirthday()>=18&&item.getBirthday()<=22){
                    cencesIdentityCard.setTwentyTwo(cencesIdentityCard.getTwentyTwo()+item.getCount());
                }
                if(item.getBirthday()>=23&&item.getBirthday()<=26){
                    cencesIdentityCard.setTwentySix(cencesIdentityCard.getTwentySix()+item.getCount());
                }
                if(item.getBirthday()>=27&&item.getBirthday()<=30){
                    cencesIdentityCard.setThrity(cencesIdentityCard.getThrity()+item.getCount());
                }
                if(item.getBirthday()>=31&&item.getBirthday()<=40){
                    cencesIdentityCard.setForty(cencesIdentityCard.getForty()+item.getCount());
                }
                if(item.getBirthday()>40){
                    cencesIdentityCard.setFortyPlus(cencesIdentityCard.getFortyPlus()+item.getCount());
                }
            });


    }
}
